package com.pp.ent.db;

/**
 * Created by dengqu on 2017/2/24.
 */


import android.annotation.SuppressLint;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.text.TextUtils;

import com.pp.ent.Cherry;
import com.pp.ent.base.common.SafeHandlerDispatch;
import com.pp.ent.base.log.MLog;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.logging.Logger;

public abstract class DbThread
        extends Thread
        implements DbContext {
    private static final int DbCommandMsg = 1;
    private static final int DbCommandResultMsg = 2;
    private static final int CreateDbHelperMsg = 3;
    private static final int CloseDbHelperMsg = 4;
    protected DbHelper dbHelper;
    protected String dbName;
    protected Logger logger;
    private CommandHandler commandHandler;
    private Handler resultHandler;
    private boolean isReady = false;
    private List<DbCommand> cachedCommands;

    public DbThread(String name, final String dbName) {
        setPriority(10);
        setName("db-" + name + "-" + dbName);

        this.dbName = dbName;
        this.logger = Logger.getLogger(name);
        MLog.debug("DbThread", "DbThread constructor");
        this.cachedCommands = Collections.synchronizedList(new ArrayList());

        this.resultHandler = new SafeHandlerDispatch(Looper.getMainLooper()) {
            public void handleMessage(Message msg) {
                switch (msg.what) {
                    case DbCommandResultMsg:
                        DbCommand cmd = (DbCommand) msg.obj;
                        if (cmd != null) {
                            DbResult dbResult = cmd.getResult();
                            String uri = cmd.getUri();
                            if (!TextUtils.isEmpty(uri)) {
                                Cherry.notifyService(cmd.getUri(), new Object[]{dbResult});
                            }
                            DbResponseLister dbResponseLister = cmd.getDbResponseLister();
                            if (dbResponseLister != null) {
                                dbResponseLister.onResponse(cmd.result);
                            }
                        }
                        break;
                }
            }
        };
    }

    public void sendCommand(DbCommand cmd) {
        if (cmd != null) {
            if (!this.isReady) {
                this.cachedCommands.add(cmd);
            } else {
                Message msg = this.commandHandler.obtainMessage(1, cmd);
                if (msg != null) {
                    this.commandHandler.sendMessage(msg);
                }
            }
        }
    }

    private void processCachedCommands() {
        if (this.dbHelper != null) {
            List<DbCommand> commands = new ArrayList(this.cachedCommands);
            if (commands.size() > 0) {
                this.logger.info("handle cached commands: " + commands.size());
                for (DbCommand cmd : commands) {
                    this.commandHandler.processCommand(cmd);
                }
            }
            commands.clear();
            commands = null;
        }
        this.cachedCommands.clear();
    }

    public void run() {
        Looper.prepare();
        if (this.dbName != null) {
            createDbHelper(this.dbName);
        }
        this.commandHandler = new CommandHandler();
        this.isReady = true;
        this.logger.info("DbThread ready");

        processCachedCommands();

        Looper.loop();
    }

    public abstract void createDbHelper(String paramString);

    protected void threadCreateDbHelper(String dbName) {
        Message msg = this.commandHandler.obtainMessage(3, dbName);
        if (msg != null) {
            this.commandHandler.sendMessage(msg);
        }
    }

    public DbHelper getDbHelper() {
        return this.dbHelper;
    }

    public void closeDbHelper() {
        if (Looper.myLooper().getThread() != this) {
            Message msg = this.commandHandler.obtainMessage(4, this.dbName);
            if (msg != null) {
                this.commandHandler.sendMessage(msg);
            }
            return;
        }
        if (this.dbHelper != null) {
            this.logger.info("close dbHelper: " + this.dbHelper.getDbName());
            this.dbHelper.close();
            this.dbHelper = null;
        }
    }

    public void open() {
        start();
    }

    public boolean isOpen() {
        return (this.dbHelper != null) && (this.dbHelper.isOpen());
    }

    @SuppressLint({"HandlerLeak"})
    private class CommandHandler
            extends SafeHandlerDispatch {
        private CommandHandler() {
        }

        public void handleMessage(Message msg) {
            switch (msg.what) {
                case DbCommandMsg:
                    DbCommand cmd = (DbCommand) msg.obj;
                    processCommand(cmd);
                    break;
                case CreateDbHelperMsg:
                    DbThread.this.dbName = ((String) msg.obj);
                    DbThread.this.createDbHelper(DbThread.this.dbName);
                    break;
                case CloseDbHelperMsg:
                    DbThread.this.closeDbHelper();
                    break;
            }
        }

        public void processCommand(DbCommand cmd) {
            if (cmd != null) {
                cmd.realExecute();
                if (DbThread.this.resultHandler != null) {
                    Message newMsg = DbThread.this.resultHandler.obtainMessage(2, cmd);
                    DbThread.this.resultHandler.sendMessage(newMsg);
                }
            }
        }
    }
}
